import json
import os
import time
from urllib.parse import quote
from datetime import datetime
import urllib.request
from app import Log
from app.response import ResponseError
from app.routes import Route
from app.session import redis
from config.config import QCloud
from model.mongo.tao.users import get_nick_name
from service import third_service, redis_service, ThirdService, mongo_service
from vendor.python_socketio_master import socketio

name = 'websocket'
socketIo = socketio.Server()
logger = Log(name).init()
route = Route(name)
websocket_wrapper = route.websocket_wrapper
namespace = '/chat'


@socketIo.on('connect', namespace=namespace)
@websocket_wrapper
def connect(sid, env):
    # logger.debug(env)
    logger.info("connect chat " + sid)
    socketIo.emit('to_join', room=sid, namespace=namespace)


@socketIo.on('disconnect', namespace=namespace)
@websocket_wrapper
def disconnect(sid):
    redis.delete(sid + '.openid')
    openid = get_openid_by_sid(sid)
    if openid:
        logger.info("openid leave " + openid)


@socketIo.on('join', namespace='/chat')
@websocket_wrapper
def join(sid, data):
    logger.info("my openid is " + data.get('id'))
    open_id = data.get('id')
    redis.set(sid + '.openid', open_id, 3600)
    redis.hset(open_id, 'sid', sid)


@socketIo.on('leave', namespace='/chat')
@websocket_wrapper
def leave(sid, data):
    openid = get_openid_by_sid(sid)
    redis.delete(sid + '.openid')
    logger.info("openid leave " + openid)


@socketIo.on('send_text', namespace=namespace)
@websocket_wrapper
def send_text(sid, data):
    print("sid=" + sid)
    openid = get_openid_by_sid(sid)
    print("open_id=" + openid)
    content = data['text_str']
    device_sn = data['sn']
    timestamp = int(data['timestamp'])
    device_type = int(data['device_type'])

    msg_content = {"content": content, "sender": openid, "time": time.time(), "type": "0"}
    if "sn" not in data or "text_str" not in data:
        msg_content["content"] += "--消息未发送成功"
        socketIo.emit('self_message', msg_content, sid, namespace=namespace)

    logger.debug(data['text_str'])
    logger.debug("device_type=" + str(device_type))
    logger.debug("openid=" + str(openid))

    try:
        if device_type == 1:
            result = ThirdService.inner_service(device_sn, 'push', [
                device_sn,
                device_type,
                openid,
                '1',
                content,
                timestamp
            ])
        else:
            result = ThirdService.inner_service(device_sn, 'family_message', [
                openid,
                device_sn,
                '0',
                content,
                timestamp
            ])

        print(result)
        print(msg_content)
        socketIo.emit('self_message', msg_content, sid, namespace=namespace)
        if result == '{"err":0}':
            add_one_message(openid, device_sn, content, 0, timestamp)

    except Exception as e:
        print(str(e))
        msg_content["content"] += "--消息未发送成功"
        socketIo.emit('self_message', msg_content, sid, namespace=namespace)


def push_msg_template(sender, receiver, content_type, timestamp):
    print(len(receiver))
    if len(receiver) < 22:
        return

    print('post_template_of_unread_message post_template_of_unread_message post_template_of_unread_message')

    nick_name = get_nick_name(receiver, sender)
    redis_service.post_template_of_unread_message(receiver, sender, nick_name, timestamp, content_type)


def add_one_message(sender, receiver, content, content_type=0, timestamp=0):
    logger.info("add_one_message")
    logger.info('|'.join(list(map(str, [sender, receiver, content, content_type, timestamp]))))
    if sender > receiver:
        l_one = sender
        s_one = receiver
    else:
        l_one = receiver
        s_one = sender

    if not timestamp:
        timestamp = int(time.time())

    data = {
        's_one': s_one,
        'l_one': l_one,
        'sender': sender,
        'content': content,
        'type': content_type,
        'time': datetime.fromtimestamp(timestamp + 8 * 3600)
    }

    mongo_service.insert('message', data)
    push_msg_template(sender, receiver, content_type, timestamp)


def handle_p8_voice_msg(openid, sn, url):
    _time = str(int(time.time()))
    return ThirdService.inner_service(sn, 'newvoice', [
        sn,
        openid + '_' + _time + '_' + sn,
        url,  # base64.encodebytes(url.encode()).decode(encoding='utf-8'),
        10,
        1,
        openid,
        _time
    ])


def docker_cmd(cmd):
    url = "http://172.27.0.9:10000/index.php?cmd=" + quote(cmd)
    req = urllib.request.Request(url)

    try:
        response = urllib.request.urlopen(
            req,
            timeout=10
        )
    except Exception as e:
        print(e)


def get_media_url(media_id):
    response = redis_service.client.media.download(media_id)
    response.raise_for_status()  # ensure we notice bad responses
    tmp_time = str(int(time.time()))
    temp_name = tmp_time + '.amr'
    temp_name_mp3 = tmp_time + '.mp3'
    file_name = os.path.join(os.path.split(os.path.realpath(__file__))[0], '../temp', temp_name)
    file_name_mp3 = os.path.join(os.path.split(os.path.realpath(__file__))[0], '../temp', temp_name_mp3)
    file = open(file_name, "wb")
    file.write(response.content)
    file.close()
    cmd = "docker run -v /var/www/:/var/www jrottenberg/ffmpeg -i " + file_name + " " + file_name_mp3
    print(cmd)
    docker_cmd(cmd)
    file_name = file_name_mp3
    temp_name = temp_name_mp3
    print(file_name)
    bucket = third_service.cos.get_bucket(QCloud.get('bucket'))
    push_res = bucket.upload_file(
        real_file_path=file_name,
        file_name=temp_name, dir_name=QCloud.get('dir'))
    url = json.loads(push_res.replace("'", '"'))['access_url']
    return url


def get_openid_by_sid(sid):
    openid = redis.get(sid + '.openid')
    if not openid:
        return None
    return openid.decode()


@socketIo.on('send_voice_msg', namespace=namespace)
@websocket_wrapper
def send_voice_msg(sid, data):
    openid = get_openid_by_sid(sid)
    timestamp = int(data['timestamp'])
    if not openid:
        raise ResponseError('no user')

    sn = data.get('sn')
    if not sn:
        raise ResponseError('no device')

    media_id = data['media_id']
    if not media_id:
        raise ResponseError('no media_id')
    media_url = get_media_url(media_id)

    device_type = data.get('device_type')
    print('device_type', device_type)

    msg_type = 1
    msg_content = {"content": media_url, "sender": openid, "time": time.time(), "type": msg_type}

    if device_type == '1':  # P8
        result = handle_p8_voice_msg(openid, sn, media_url)
    else:
        result = ThirdService.inner_service(sn, 'family_message', [
            openid, sn, 1, media_url, timestamp
        ])
    print("result=" + result)
    if result == '{"err":0}':
        add_one_message(openid, sn, media_url, msg_type)

    socketIo.emit('self_message', msg_content, sid, namespace=namespace)

# @socketIo.on('send_voice', namespace=namespace)
# @websocket_wrapper
# def send_voice(data):
#     room = session.get('room')
#     message = '我: {}'.format(data)
#     socketIo.emit('message', message, room=room)
